package com.hp.appfw.service.cust;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.apache.log4j.Logger;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hp.appfw.data.mode.mygen.*;
import com.hp.appfw.util.*;

@Service("messageCenterService")
public class MessageCenterService {
	private static final int SEND_PKG_SIZE = 1000;

	@Resource
	private JmsTemplate emailTemplate;
	@Resource
	private JmsTemplate smsTemplate;
	@Resource
	private JmsTemplate terminalTemplate;
	@Resource
	private MsgUserService userService;
	@Resource 
	private MsgMissionService missionService;
	@Resource
	private MsgLogService logService;
	
	
	private static final String EMAIL_TYPE="Email";
	private static final String SMS_TYPE="Sms";
	private static final String TERMINAL_TYPE="Terminal";
	

	private static Logger logger = Logger.getLogger(MessageCenterService.class);

	public BaseMessageMission createEmailMission(String title, String content, String entId) throws Exception
	{
		return createMission(EMAIL_TYPE, title, content, entId);
	}
	public BaseMessageMission createSmsMission(String title, String content, String entId) throws Exception
	{
		return createMission(SMS_TYPE, title, content, entId);
	}
	public BaseMessageMission createTerminalMission(String title, HashMap<String, String> content, String entId) throws Exception
	{
        ObjectMapper mapper = new ObjectMapper();
        String jsonContent = mapper.writeValueAsString(content);
	
		return createMission(TERMINAL_TYPE, title, jsonContent, entId);
	}
	private BaseMessageMission createMission(String type, String title, String content, String entId) throws Exception
	{
		BaseMessageMission mission = new BaseMessageMission();
		mission.setId(UUID.randomUUID().toString());
		mission.setTitle(title);
		mission.setContent(content);
		mission.setType(type);
		mission.setStartTime(new Date());
		mission.setFinishCount(0);
		mission.setTotalCount(0);
		mission.setStatus("Create");
		mission.setEntId(entId);
		
		missionService.insert(mission);

		logger.info("Create Mission Success:\r\n" + ClassUtil.getClassInfo(mission));
		return mission;
	}
	
	//small number(< 1000) send, return 0:success, >0:error message number. BaseMessageLog has 3 type: Email, Sms, Terminal. 
	public int sendMessage(BaseMessageMission mission, List<BaseMessageLog> list) throws Exception
	{
		int errorCount = 0;
		int procCount = 0;
		
		if(list.size() == 0)
			return 0;
		
		logger.info("[" + mission.getId() + "]Messages are starting to be send:\r\n" + ClassUtil.getClassInfo(mission));

		int i;
		for(i = 0; i < list.size(); i ++)
		{
			BaseMessageLog item = list.get(i);
			BaseUser user = userService.getItem(item.getRecieverId());
			if(user != null && item.getMissionId().equals(mission.getId()) && item.getType().equals(mission.getType()))
			{
				
				final BaseMessageLog ml = item;
				//push message into queue
				switch(item.getType())
				{
					case EMAIL_TYPE:
					{
						//insert log
						item.setId(UUID.randomUUID().toString());
						item.setStatus("Create");
						item.setReciever(user.getEmail());
						item.setEntId(mission.getEntId());
						
						logService.insert(item);

						emailTemplate.send(new MessageCreator() {  
					        public Message createMessage(Session session) throws JMSException {
					        	return session.createObjectMessage(ml);
					        }  
					    });
						
						procCount ++;
						break;
					}
					case SMS_TYPE:
					{
						//insert log
						item.setId(UUID.randomUUID().toString());
						item.setStatus("Create");
						item.setReciever(user.getCellphone());
						item.setEntId(mission.getEntId());
						
						logService.insert(item);

						smsTemplate.send(new MessageCreator() {  
					        public Message createMessage(Session session) throws JMSException {
					        	return session.createObjectMessage(ml);
					        }
					    });
						procCount ++;
						break;
					}
					case TERMINAL_TYPE:
					{
						//insert log
						item.setId(UUID.randomUUID().toString());
						item.setStatus("Create");
						item.setEntId(mission.getEntId());
						item.setReciever(user.getId());
						
						logService.insert(item);

						terminalTemplate.send(new MessageCreator() {  
					        public Message createMessage(Session session) throws JMSException {
					        	return session.createObjectMessage(ml);
					        }
					    });
						procCount ++;
						break;
					}
					default:
					{
						logger.error("[" + mission.getId() + "]Unknown Messages type:\r\n" + ClassUtil.getClassInfo(mission) + "\r\n" + ClassUtil.getClassInfo(item));
						errorCount ++;
					}
				}
				logger.info("[" + mission.getId() + "]Send " + procCount + " messages success, error " + errorCount + " :\r\n" + ClassUtil.getClassInfo(item));
			}
			else
			{
				errorCount ++;
				if(user == null)
					logger.error("[" + mission.getId() + "]Can't find receiver:\r\n" + ClassUtil.getClassInfo(mission) + "\r\n" + ClassUtil.getClassInfo(item));
				else
					logger.error("[" + mission.getId() + "]Log info can't match the mission:\r\n" + ClassUtil.getClassInfo(mission) + "\r\n" + ClassUtil.getClassInfo(item));
			}
		}
		
		//update mission
		mission = missionService.getItem(mission.getId());
		mission.setTotalCount(mission.getTotalCount() + procCount);
		mission.setStatus("Send");
		logger.info("[" + mission.getId() + "]Messages had been send over. Push all " + procCount + " to queue. Error " + errorCount);
		logger.info("[" + mission.getId() + "]Update mission total count:\r\n" + ClassUtil.getClassInfo(mission));
		missionService.update(mission);
		
		return errorCount;
	}

	public int sendMassMessage(BaseMessageMission mission, List<BaseMessageLog> list) throws Exception
	{
		int errorCount = 0;
		int curErrCount;
		int count = list.size();
		int cycleCount = count / SEND_PKG_SIZE;
		int cycleLeft = count % SEND_PKG_SIZE;
		int i;
		int j;
		logger.info("[" + mission.getId() + "]Mass messages are starting to be send:\r\n" + ClassUtil.getClassInfo(mission));
		
		for(i = 0; i < cycleCount; i ++)
		{
			List<BaseMessageLog> clist = new ArrayList<BaseMessageLog>();
			for(j = 0; j < SEND_PKG_SIZE; j++)
			{
				clist.add(list.get(i * SEND_PKG_SIZE + j));
			}
			curErrCount = sendMessage(mission, clist);
			errorCount += curErrCount;
		}
		
		if(cycleLeft > 0)
		{
			List<BaseMessageLog> clist = new ArrayList<BaseMessageLog>();
			for(j = 0; j < cycleLeft; j++)
			{
				clist.add(list.get(cycleCount * SEND_PKG_SIZE + j));
			}
			curErrCount = sendMessage(mission, clist);
			errorCount += curErrCount;
		}
		
		logger.info("[" + mission.getId() + "]Mass messages had been send over. Send all " + list.size() + " messages. Error number " + errorCount);
		
		return errorCount;
	}
}
